[アップデート] AWS Lambda がログを送信する CloudWatch ロググループをカスタマイズ可能になり、複数の Lambda 関数のログを集約できるようになりました
こんにちは、CX 事業本部 Delivery 部の若槻です。
最近の AWS Lambda アップデートで、ログ出力の仕様を柔軟に設定できる機能が追加されました。
上記アップデートで追加された機能は以下の 3 つです。
- Lambda のログを独自のロギングライブラリを使用せずに JSON 構造化形式でキャプチャ可能に
- Lambda のログレベル(ERROR, DEBUG, INFO など)をコードを変更することなく制御できる
- Lambda がログを送信する CloudWatch ロググループを選択できる
今回はこのうち 3 つ目のアップデートである、Lambda がログを送信する CloudWatch ロググループを選択可能となった 機能について実際に試してみました。
何が嬉しいのか
Lambda 関数では既定では /aws/lambda/< 関数名 >
というロググループにログが送信されますが、今回のアップデートにより任意のロググループを指定することも可能になりました。
これにより何が嬉しいのかと言うと、複数の関数のログを 1 つのロググループに集約できるようになることです。単一のアプリケーションや関連する一連の処理が複数の Lambda 関数から構成されている場合、ログの出力先が単一のロググループにまとめられている方が便利な場合もあるためです。
いくつか例を挙げます。
1 つ目は下記で紹介されているような方法で CloudWatch Logs に書き込まれたログを Kinesis Data Firehose で他の場所に配信したい場合に、ロググループが集約されている場合は Lambda 関数の個数分の Firehose をセットアップする必要が無くなり、コスト削減や管理の簡素化につながります。
2 つ目は、マネジメントコンソールから CloudWatch Logs Insights でデバッグを行う際に、複数の Lambda のログをクエリしたい場合でも Lambda の数だけロググループを選択する必要が無くなります。
ロググループを集約しない場合は、クエリする必要があるすべてのロググループを選択する必要があります。
3 つ目は、下記で紹介しているような方法で Lambda のアプリケーションエラーをチャットツールに通知したい場合に、Lambda 関数ごとに CloudWatch Logs メトリクスフィルターや CloudWatch Alarm などのリソースを構成する必要が無くなります。Lambda 関数が多い場合にこの通知の構成でリソース数が増えすぎて Cfn スタックのハードリミットに抵触するなんていう悲劇も防げます。
このように、Lambda がログを送信する CloudWatch ロググループを選択できるようになることで、ログデータの取り回しを簡素化できる場合があり、なかなか嬉しいアップデートになっています。
ただし注意点として、個別のログと出力元の Lambda 関数を紐付けられるようにするための工夫は必要です。以降の「やってみた」では出力される構造化ログに Lambda 関数名および Arn を追加して紐づけ可能とする方法を含め紹介します。
やってみた
検証用リソース作成
ログ出力先のロググループ 1 つと、ログを出力する lambda 関数 2 つを AWS CDK で作成します。
CDK コード
import { aws_lambda_nodejs, aws_lambda, aws_logs, Stack, StackProps, RemovalPolicy, } from 'aws-cdk-lib'; import { Construct } from 'constructs'; export class CdkSampleStack extends Stack { constructor(scope: Construct, id: string, props: StackProps) { super(scope, id, props); // ロググループ const logGroup = new aws_logs.LogGroup(this, 'CustomLogGroup', { logGroupName: '/custom/lambda/sample-app', removalPolicy: RemovalPolicy.DESTROY, }); // Lambda 関数 1 new aws_lambda_nodejs.NodejsFunction(this, 'SampleFunc1', { functionName: 'sample-app-func-1', runtime: aws_lambda.Runtime.NODEJS_20_X, architecture: aws_lambda.Architecture.ARM_64, entry: 'src/handler.ts', logGroup, }); // Lambda 関数 2 new aws_lambda_nodejs.NodejsFunction(this, 'SampleFunc2', { functionName: 'sample-app-func-2', runtime: aws_lambda.Runtime.NODEJS_20_X, architecture: aws_lambda.Architecture.ARM_64, entry: 'src/handler.ts', logGroup, }); } }
v2.110.0 のリリースより aws_lambda_nodejs.NodejsFunction
(aws_lambda.Function
)でも今回のロギングの機能が設定可能になっています。そして新規追加された logGroup
プロパティでロググループを指定することで、Lambda がログを送信する CloudWatch ロググループを選択できます。
ハンドラーコード
ハンドラーコードは 2 つの Lambda 関数で共通のものを使用します。
import { Logger, injectLambdaContext } from '@aws-lambda-powertools/logger'; import middy from '@middy/core'; const logger = new Logger({ logLevel: 'INFO', serviceName: 'sample-app', }); const lambdaHandler = async (): Promise<void> => { logger.info('Hello, world!'); }; export const handler = middy(lambdaHandler).use(injectLambdaContext(logger));
下記で紹介されている Powertools を使用した方法により、構造化ログに Lambda 関数名や Arn などのコンテキスト情報を追加しています。
動作確認
前述のコードでリソースを作成したら、2 つの Lambda 関数を実行してログを確認します。
まず 2 つの関数を実行します。
aws lambda invoke \ --function-name sample-app-func-1 \ outputfile.txt aws lambda invoke \ --function-name sample-app-func-2 \ outputfile.txt
実行後にマネジメントコンソールからロググループを確認すると、以下のように 2 つの関数が出力したログが 1 つのロググループに出力されていることが確認できます。
なおログストリームはその名前に関数名を含むので、関数ごとに分けて作成されます。< 関数名 >< エイリアス名 >
のようなキーワードでフィルターすれば、目当ての関数のログを含むログストリームのみ確認できるのは地味に嬉しいです。
ログストリームを開くと、それぞれの関数が出力したログが確認できます。
{ "cold_start": true, "function_arn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sample-app-func-1", "function_memory_size": 128, "function_name": "sample-app-func-1", "function_request_id": "220fa28d-c4d9-46d7-a379-ef922fe1609f", "level": "INFO", "message": "Hello, world!", "service": "sample-app", "timestamp": "2023-11-18T16:14:45.069Z", "xray_trace_id": "1-6558e2f4-5fc8c0115d8dd2e63e16b9df" }
{ "cold_start": true, "function_arn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:sample-app-func-2", "function_memory_size": 128, "function_name": "sample-app-func-2", "function_request_id": "2b5e4fde-7b0c-4697-a4aa-a052c5e0e611", "level": "INFO", "message": "Hello, world!", "service": "sample-app", "timestamp": "2023-11-18T16:14:46.178Z", "xray_trace_id": "1-6558e2f5-52b265b52e4dccaa4754edd3" }
構造化ログに Lambda 関数名および Arn が追加されているので、それぞれのログがどの Lambda から出力されたものであるかを確認できるようになっていますね。
おわりに
AWS Lambda がログを送信する CloudWatch ロググループをカスタマイズ可能になり、複数の Lambda 関数のログを集約できるようになったのでご紹介しました。
冒頭で紹介したように様々なケースで活用できるアップデートだと思うので、ぜひ試してみてください。
参考
以上